from fastapi import APIRouter, Depends, HTTPException, Query
from sqlalchemy.orm import Session
from datetime import date, datetime, timedelta
import logging

from backend.config.database import get_db
from backend.service.data_sync_service import DataSyncService, sync_powerload, sync_weather
from backend.service.data_update_service import DataUpdateService
from backend.service.prediction_service import SimplePredictionModel
from backend.service.weather_forecast_service import weather_forecast_service

logger = logging.getLogger(__name__)
router = APIRouter(prefix="/data-sync", tags=["数据同步"])

@router.get("/health")
async def health_check():
    """健康检查接口"""
    try:
        return {
            "status": "ok",
            "message": "服务正常运行",
            "timestamp": datetime.now().isoformat(),
            "version": "1.0.0"
        }
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"健康检查失败: {str(e)}")

@router.get("/status")
async def get_sync_status(db: Session = Depends(get_db)):
    """获取数据同步状态"""
    try:
        from backend.entities.load_data_new import LoadData
        from backend.entities.weather_daily import WeatherDaily
        
        # 检查最近的数据
        yesterday = datetime.now() - timedelta(days=1)
        yesterday_date = yesterday.date()
        
        # 检查负荷数据
        load_data = db.query(LoadData).filter(LoadData.dt == yesterday_date).first()
        powerload_status = load_data is not None
        
        # 检查气象数据
        weather_data = db.query(WeatherDaily).filter(WeatherDaily.dt == yesterday_date).first()
        weather_status = weather_data is not None
        
        # 检查后端连接
        backend_connected = True  # 如果能到达这里，说明后端连接正常
        
        return {
            "powerload_status": "complete" if powerload_status else "incomplete",
            "weather_status": "complete" if weather_status else "incomplete", 
            "backend_connected": backend_connected,
            "last_updated": yesterday.isoformat(),
            "data_sources": {
                "load_data_source": "ENTSO-E API（欧洲输电系统运营商网络）",
                "weather_data_source": "Visual Crossing API"
            },
            "location": "比利时"
        }
        
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"获取同步状态失败: {str(e)}")

@router.get("/check-availability")
async def check_data_availability(
    date: str = Query(..., description="检查日期，格式：YYYY-MM-DD"),
    db: Session = Depends(get_db)
):
    """检查指定日期的数据是否已存在"""
    try:
        from backend.entities.load_data_new import LoadData
        from backend.entities.weather_daily import WeatherDaily
        
        # 解析日期
        check_date = datetime.strptime(date, '%Y-%m-%d').date()
        
        # 检查负荷数据
        load_exists = db.query(LoadData).filter(LoadData.dt == check_date).first() is not None
        
        # 检查气象数据
        weather_exists = db.query(WeatherDaily).filter(WeatherDaily.dt == check_date).first() is not None
        
        return {
            "date": date,
            "has_data": load_exists and weather_exists,
            "load_data_exists": load_exists,
            "weather_data_exists": weather_exists,
            "message": "数据可用性检查完成"
        }
        
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"数据可用性检查失败: {str(e)}")

@router.get("/check-missing")
async def check_missing_data(
    start_date: str = Query(..., description="开始日期，格式：YYYY-MM-DD"),
    end_date: str = Query(..., description="结束日期，格式：YYYY-MM-DD"),
    db: Session = Depends(get_db)
):
    """检查指定日期范围内缺失的数据"""
    try:
        sync_service = DataSyncService()
        missing_info = sync_service.check_missing_data(start_date, end_date)
        
        return {
            "status": "ok",
            "message": "缺失数据检查完成",
            "missing_info": missing_info
        }
        
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"检查缺失数据失败: {str(e)}")

@router.post("/sync-all")
async def sync_all_data(
    target_date: str = "",
    weather_data_source: str = "auto",
    days: int = Query(1, description="要同步的天数，默认1天（单日同步）"),
    db: Session = Depends(get_db)
):
    """一键更新数据 - 智能检测并同步缺失的负荷和气象数据"""
    try:
        # 如果没有指定日期，使用前一天
        if not target_date:
            yesterday = datetime.now() - timedelta(days=1)
            target_date = yesterday.strftime('%Y-%m-%d')
        
        # 如果指定了天数大于1，则同步多天数据
        if days > 1:
            # 计算日期范围
            end_date = datetime.strptime(target_date, '%Y-%m-%d')
            start_date = end_date - timedelta(days=days-1)
            
            start_date_str = start_date.strftime('%Y-%m-%d')
            end_date_str = end_date.strftime('%Y-%m-%d')
            
            logger.info(f"开始检查并同步 {days} 天的缺失数据: {start_date_str} 到 {end_date_str}")
            
            # 使用DataSyncService同步缺失数据
            sync_service = DataSyncService()
            sync_result = sync_service.sync_missing_data(start_date_str, end_date_str)
            
            # 添加同步范围信息
            sync_result["sync_range"] = {
                "start_date": start_date_str,
                "end_date": end_date_str,
                "days": days
            }
            
            # 添加详细的状态信息
            if "sync_info" in sync_result:
                sync_info = sync_result["sync_info"]
                logger.info(f"同步结果 - 总天数: {sync_info.get('total_days', 0)}, "
                          f"缺失负荷数据: {sync_info.get('missing_load_count', 0)}天, "
                          f"缺失气象数据: {sync_info.get('missing_weather_count', 0)}天")
            
            return sync_result
        else:
            # 单日同步逻辑
            # 检查数据是否已存在
            check_response = await check_data_availability(target_date, db)
            if check_response["has_data"]:
                return {
                    "status": "ok",
                    "message": f"{target_date} 的数据已存在，无需同步",
                    "date": target_date,
                    "skipped": True
                }
            
            # 使用DataSyncService同步数据
            sync_service = DataSyncService()
            success = sync_service.sync_daily_data(target_date, weather_data_source)
            
            if success:
                return {
                    "status": "ok",
                    "message": f"{target_date} 数据同步成功 (气象数据源: {weather_data_source})",
                    "date": target_date,
                    "weather_data_source": weather_data_source,
                    "load_success": True,
                    "weather_success": True
                }
            else:
                return {
                    "status": "warning",
                    "message": f"{target_date} 数据同步失败",
                    "date": target_date,
                    "weather_data_source": weather_data_source,
                    "load_success": False,
                    "weather_success": False
                }
            
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"数据同步失败: {str(e)}")

@router.post("/sync-daily")
async def sync_daily_data(
    target_date: str = "",
    db: Session = Depends(get_db)
):
    """同步指定日期的数据"""
    try:
        sync_service = DataSyncService()
        success = sync_service.sync_daily_data(target_date)
        
        if success:
            return {"message": "数据同步成功", "date": target_date or "今天"}
        else:
            raise HTTPException(status_code=500, detail="数据同步失败")
            
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"数据同步异常: {str(e)}")

@router.post("/sync-weather/{start_date}/{end_date}")
async def sync_weather_range(
    start_date: str,
    end_date: str,
    db: Session = Depends(get_db)
):
    """同步指定日期范围的气象数据"""
    try:
        sync_service = DataSyncService()
        success = sync_service.sync_weather_data(start_date, end_date)
        
        if success:
            return {"message": "气象数据同步成功", "start_date": start_date, "end_date": end_date}
        else:
            raise HTTPException(status_code=500, detail="气象数据同步失败")
            
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"气象数据同步异常: {str(e)}")

@router.post("/sync-load/{start_date}/{end_date}")
async def sync_load_range(
    start_date: str,
    end_date: str,
    db: Session = Depends(get_db)
):
    """同步指定日期范围的负荷数据"""
    try:
        sync_service = DataSyncService()
        success = sync_service.sync_load_data(start_date, end_date)
        
        if success:
            return {"message": "负荷数据同步成功", "start_date": start_date, "end_date": end_date}
        else:
            raise HTTPException(status_code=500, detail="负荷数据同步失败")
            
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"负荷数据同步异常: {str(e)}")

@router.post("/train-models")
async def train_all_models(db: Session = Depends(get_db)):
    """训练所有预测模型"""
    try:
        model = SimplePredictionModel()
        results = model.train_all_models()
        
        success_count = sum(1 for success in results.values() if success)
        total_count = len(results)
        
        return {
            "message": f"模型训练完成，成功: {success_count}/{total_count}",
            "results": results
        }
        
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"模型训练异常: {str(e)}")

@router.post("/predict-future/{days}")
async def predict_future_days(
    days: int = 7,
    db: Session = Depends(get_db)
):
    """生成未来几天的预测数据"""
    try:
        if days < 1 or days > 30:
            raise HTTPException(status_code=400, detail="预测天数必须在1-30之间")
        
        model = SimplePredictionModel()
        results = model.predict_all_models(days)
        
        success_count = sum(1 for success in results.values() if success)
        total_count = len(results)
        
        return {
            "message": f"预测完成，成功: {success_count}/{total_count}",
            "days": days,
            "results": results
        }
        
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"预测异常: {str(e)}")

@router.post("/initialize-system")
async def initialize_system(db: Session = Depends(get_db)):
    """初始化系统数据"""
    try:
        sync_service = DataSyncService()
        model = SimplePredictionModel()
        
        # 1. 同步历史数据 (最近30天)
        from datetime import datetime, timedelta
        end_date = datetime.now().strftime('%Y-%m-%d')
        start_date = (datetime.now() - timedelta(days=30)).strftime('%Y-%m-%d')
        
        load_success = sync_service.sync_load_data(start_date, end_date)
        weather_success = sync_service.sync_weather_data(start_date, end_date)
        
        # 2. 训练模型
        train_results = model.train_all_models()
        
        # 3. 生成未来7天预测
        predict_results = model.predict_all_models(7)
        
        return {
            "message": "系统初始化完成",
            "data_sync": {
                "load_data": load_success,
                "weather_data": weather_success
            },
            "model_training": train_results,
            "predictions": predict_results
        }
        
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"系统初始化异常: {str(e)}")

# 兼容旧版API的路由
@router.post("/powerload")
def manual_sync_powerload():
    """
    手动同步电力负荷数据（20160101至今，已存在则跳过）
    """
    return sync_powerload()

@router.post("/weather")
def manual_sync_weather():
    """
    手动同步气象数据（20160101至今，已存在则跳过）
    """
    return sync_weather()

# ===================== ENTSO-E API 数据更新接口 =====================

@router.post("/update-yesterday")
async def update_yesterday_data(db: Session = Depends(get_db)):
    """
    使用ENTSO-E API更新前一天的数据到数据库
    
    功能:
    - 获取前一天的电力负荷数据 (ENTSO-E API)
    - 获取前一天的气象数据 (OpenMeteo API)
    - 自动判断节假日信息
    - 保存到数据库
    """
    try:
        update_service = DataUpdateService()
        result = update_service.update_yesterday_data()
        
        if result['success']:
            return {
                "success": True,
                "message": result['message'],
                "details": result['details']
            }
        else:
            raise HTTPException(status_code=500, detail=result['error'])
            
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"更新前一天数据失败: {str(e)}")

@router.post("/update-custom-date")
async def update_custom_date_data(
    target_date: str = Query(..., description="目标日期，格式：YYYY-MM-DD"),
    db: Session = Depends(get_db)
):
    """
    使用ENTSO-E API更新指定日期的数据到数据库
    
    功能:
    - 获取指定日期的电力负荷数据 (ENTSO-E API)
    - 获取指定日期的气象数据 (OpenMeteo API)
    - 自动判断节假日信息
    - 保存到数据库
    """
    try:
        # 验证日期格式
        try:
            datetime.strptime(target_date, '%Y-%m-%d')
        except ValueError:
            raise HTTPException(status_code=400, detail="日期格式错误，请使用YYYY-MM-DD格式")
        
        update_service = DataUpdateService()
        result = update_service.update_custom_date_data(target_date)
        
        if result['success']:
            return {
                "success": True,
                "message": result['message'],
                "details": result['details']
            }
        else:
            raise HTTPException(status_code=500, detail=result['error'])
            
    except HTTPException:
        raise
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"更新指定日期数据失败: {str(e)}")

@router.get("/validate-token")
async def validate_entsoe_token(db: Session = Depends(get_db)):
    """
    验证ENTSO-E API token是否有效
    """
    try:
        from backend.utils.entsoe_api import ENTSOEAPIService
        
        api_service = ENTSOEAPIService()
        is_valid = api_service.validate_token()
        
        return {
            "success": True,
            "token_valid": is_valid,
            "message": "ENTSO-E API token验证成功" if is_valid else "ENTSO-E API token验证失败"
        }
        
    except Exception as e:
        return {
            "success": False,
            "token_valid": False,
            "message": f"验证token时发生错误: {str(e)}"
        }

@router.post("/update-weather-forecast")
async def update_weather_forecast():
    """更新气象预报数据（今天和未来6天）"""
    try:
        success = weather_forecast_service.update_weather_forecast()
        
        if success:
            return {
                "status": "ok",
                "message": "气象预报数据更新成功",
                "forecast_days": 7,
                "data_source": "Open Meteo API"
            }
        else:
            return {
                "status": "error",
                "message": "气象预报数据更新失败",
                "forecast_days": 7,
                "data_source": "Open Meteo API"
            }
            
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"气象预报数据更新失败: {str(e)}")

@router.get("/weather-forecast-status")
async def get_weather_forecast_status(db: Session = Depends(get_db)):
    """获取气象预报数据状态"""
    try:
        from backend.entities.weather_daily import WeatherDaily
        from datetime import date, timedelta
        
        # 获取今天和未来6天的日期
        today = date.today()
        future_dates = []
        for i in range(7):
            future_dates.append(today + timedelta(days=i))
        
        # 检查数据库中是否有这些日期的气象数据
        forecast_status = {}
        for forecast_date in future_dates:
            weather_record = db.query(WeatherDaily).filter(
                WeatherDaily.dt == forecast_date
            ).first()
            
            forecast_status[forecast_date.isoformat()] = {
                "date": forecast_date.isoformat(),
                "has_data": weather_record is not None,
                "is_today": forecast_date == today,
                "days_ahead": (forecast_date - today).days
            }
        
        return {
            "status": "ok",
            "forecast_status": forecast_status,
            "total_days": len(future_dates),
            "available_days": sum(1 for status in forecast_status.values() if status["has_data"]),
            "data_source": "Open Meteo API"
        }
        
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"获取气象预报状态失败: {str(e)}")

@router.get("/data-status")
async def get_data_status(db: Session = Depends(get_db)):
    """检查负荷和气象数据的截止日期状态"""
    try:
        from backend.entities.load_data_new import LoadData
        from backend.entities.weather_daily import WeatherDaily
        
        # 获取前一天日期
        yesterday = datetime.now() - timedelta(days=1)
        yesterday_date = yesterday.date()
        yesterday_str = yesterday.strftime('%Y-%m-%d')
        
        # 检查负荷数据最新日期
        latest_load = db.query(LoadData).order_by(LoadData.dt.desc()).first()
        load_latest_date = None
        load_is_current = False
        
        if latest_load is not None and hasattr(latest_load, 'dt'):
            load_latest_date = latest_load.dt
            if hasattr(load_latest_date, 'strftime'):
                load_date_str = load_latest_date.strftime('%Y-%m-%d')
                load_is_current = load_date_str >= yesterday_str
            else:
                load_date_str = str(load_latest_date)
                load_is_current = load_date_str >= yesterday_str
        
        # 检查气象数据最新日期
        latest_weather = db.query(WeatherDaily).order_by(WeatherDaily.dt.desc()).first()
        weather_latest_date = None
        weather_is_current = False
        
        if latest_weather is not None and hasattr(latest_weather, 'dt'):
            weather_latest_date = latest_weather.dt
            if hasattr(weather_latest_date, 'strftime'):
                weather_date_str = weather_latest_date.strftime('%Y-%m-%d')
                weather_is_current = weather_date_str >= yesterday_str
            else:
                weather_date_str = str(weather_latest_date)
                weather_is_current = weather_date_str >= yesterday_str
        
        return {
            "load_data": {
                "latest_date": load_latest_date.strftime('%Y-%m-%d') if load_latest_date and hasattr(load_latest_date, 'strftime') else None,
                "is_current": load_is_current,
                "needs_update": not load_is_current
            },
            "weather_data": {
                "latest_date": weather_latest_date.strftime('%Y-%m-%d') if weather_latest_date and hasattr(weather_latest_date, 'strftime') else None,
                "is_current": weather_is_current,
                "needs_update": not weather_is_current
            },
            "yesterday": yesterday_str,
            "all_current": load_is_current and weather_is_current,
            "message": "数据状态检查完成"
        }
        
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"数据状态检查失败: {str(e)}")

@router.post("/sync-to-yesterday")
async def sync_to_yesterday(db: Session = Depends(get_db)):
    """同步数据到前一天"""
    try:
        # 获取前一天日期
        yesterday = datetime.now() - timedelta(days=1)
        yesterday_str = yesterday.strftime('%Y-%m-%d')
        
        # 检查当前数据状态
        status_response = await get_data_status(db)
        status_data = status_response
        
        # 如果数据已经是最新的，直接返回
        if status_data.get('all_current', False):
            return {
                "status": "ok",
                "message": f"数据已是最新，截止到 {yesterday_str}",
                "data_status": status_data
            }
        
        # 同步前一天的数据
        sync_service = DataSyncService()
        sync_result = sync_service.sync_daily_data(yesterday_str)
        
        if sync_result:
            # 重新检查状态
            updated_status = await get_data_status(db)
            return {
                "status": "ok",
                "message": f"数据同步成功，截止到 {yesterday_str}",
                "data_status": updated_status
            }
        else:
            return {
                "status": "fail",
                "message": f"数据同步失败",
                "data_status": status_data
            }
            
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"同步到前一天失败: {str(e)}")

@router.post("/sync-multiple-days")
async def sync_multiple_days(
    days: int = Query(7, description="要同步的天数，默认7天"),
    db: Session = Depends(get_db)
):
    """一键同步前数天的数据，截止到前一天"""
    try:
        # 计算日期范围
        yesterday = datetime.now() - timedelta(days=1)
        end_date = yesterday
        start_date = yesterday - timedelta(days=days-1)  # 包含end_date，所以减days-1
        
        start_date_str = start_date.strftime('%Y-%m-%d')
        end_date_str = end_date.strftime('%Y-%m-%d')
        
        # logger.info(f"开始同步 {days} 天的数据: {start_date_str} 到 {end_date_str}") # Original code had this line commented out
        
        # 检查当前数据状态
        status_response = await get_data_status(db)
        status_data = status_response
        
        # 使用DataSyncService同步数据
        sync_service = DataSyncService()
        
        # 同步负荷数据
        load_success = sync_service.sync_load_data(start_date_str, end_date_str)
        
        # 同步气象数据
        weather_success = sync_service.sync_weather_data(start_date_str, end_date_str)
        
        if load_success and weather_success:
            # 重新检查状态
            updated_status = await get_data_status(db)
            return {
                "status": "ok",
                "message": f"成功同步 {days} 天的数据，截止到 {end_date_str}",
                "sync_range": {
                    "start_date": start_date_str,
                    "end_date": end_date_str,
                    "days": days
                },
                "sync_results": {
                    "load_success": load_success,
                    "weather_success": weather_success
                },
                "data_status": updated_status
            }
        else:
            return {
                "status": "warning",
                "message": f"部分数据同步失败，截止到 {end_date_str}",
                "sync_range": {
                    "start_date": start_date_str,
                    "end_date": end_date_str,
                    "days": days
                },
                "sync_results": {
                    "load_success": load_success,
                    "weather_success": weather_success
                },
                "data_status": status_data
            }
            
    except Exception as e:
        # logger.error(f"同步多天数据失败: {e}") # Original code had this line commented out
        return {
            "status": "error",
            "message": f"同步失败: {str(e)}",
            "data_status": await get_data_status(db)
        }